import clang.cindex

class _TemplateWithLevel:
    def __init__(self,lvl,temp):
        self.level=lvl
        self.template=temp
    level=""
    template=""
    
    
currentLevel=0
currentTemplateData=[]
parsingFileName=""
parsingFileData=[]
oldParsedFileData=""
def loadFileData(fName):
    global oldParsedFileData
    if fName==oldParsedFileData:
        return
    oldParsedFileData=fName
    global parsingFileData
    parsingFileData=[]
    for line in open(fName,'r').readlines():
        line=line.replace("\n","")
        putData=[]
        for x in line:
            putData.append(x)
        parsingFileData.append(putData)

def getEqualType(fData,sData):
    if type(fData).__name__=="dict":
        if type(sData).__name__=="dict":
            ceqType=2
        else:
            return 4
    elif type(fData).__name__=="bool" or type(fData).__name__=="int" or type(fData).__name__=="str":
        if type(sData).__name__=="bool" or type(sData).__name__=="int" or type(sData).__name__=="str":
            ceqType=1
        else:
            return 4
    elif hasattr(fData,"equals"):
        if hasattr(sData,"equals"):
            ceqType=0
        else:
            return 4
    else:
        if type(fData).__name__==type(sData).__name__:
            ceqType=1
        else:
            return 4
    return ceqType
def dataEquals(fData,sData,eqType=3):
    if len(fData)!=len(sData):
        return False
    ceqType=eqType
    for x in range(0,len(fData)):
        if eqType==3:
            ceqType=getEqualType(fData.values()[x],sData.values()[x])
            if ceqType==4:
                return False
        if ceqType==0:
            if fData.values()[x].equals(sData.values()[x])==False:
                return False
        elif ceqType==1:
            if fData.values()[x]!=sData.values()[x]:
                return False
        elif ceqType==2:
            if dataEquals(fData.values()[x],sData.values()[x])==False:
                return False
    return True

def getTextFromSourceRange(ext):
    if ext==None:
        return ""
    if ext.start==None or ext.end==None:
        return ""
    if ext.start.file==None or ext.end.file==None:
        return ""
    if ext.start.file.name[len(ext.start.file.name)-2:]!=".h" and ext.start.file.name[len(ext.start.file.name)-4:]!=".cpp":
        return ""
    loadFileData(ext.start.file.name)
    start=ext.start
    end=ext.end
    txt=""
    for p in range(start.line-1,end.line):
        if p>=len(parsingFileData):
            return txt
        if txt!="":
            txt=txt+"\n"
        if p==start.line-1 and p==end.line-1:
            for c in range(start.column-1,end.column-1):
                if c<len(parsingFileData[p]):
                    txt=txt+parsingFileData[p][c]
        elif p==end.line-1:
            for c in range(0,end.column-1):
                if c<len(parsingFileData[p]):
                    txt=txt+parsingFileData[p][c]
        elif p==start.line-1:
            for c in range(start.column-1,len(parsingFileData[p])-1):
                if c<len(parsingFileData[p]):
                    txt=txt+parsingFileData[p][c]
        else:
            txt=txt+str(parsingFileData[p])
    return txt
def increaseTemplateLevel():
    global currentTemplateData
    global currentLevel
    return currentLevel+1
    
def addTemplateLevel(tmpl):
    global currentTemplateData
    global currentLevel
    x=_TemplateWithLevel(currentLevel,tmpl)
    currentTemplateData.append(x)

def hasTemplateLevel(tmpl):
    global currentTemplateData
    global currentLevel
    for x in currentTemplateData:
        if x.template==tmpl:
            return True
    return False

def decreaseTemplateLevel():
    global currentTemplateData
    global currentLevel
    currentLevel=currentLevel-1
    newTable=[]
    for x in currentTemplateData:
        if x.level>currentLevel:
            newTable.append(x)
    currentTemplateData=newTable
    
builtinTypes=["int","float","void","double","char","bool","short","long"]
def isBuiltinType(x):
    if x in builtinTypes:
        return True
    return False
def getArrayData(st):
    if st==None:
        return []
    openedArray=0
    rstr=""
    for c in range(0,len(st)):
        c=(len(st)-1)-c
        char=st[c]
        if openedArray==0 and char!=']' and char!='[':
            return ""
        if char==']':
            openedArray=openedArray+1
        elif char=='[':
            openedArray=openedArray-1
        
        if openedArray>0:
            rstr=rstr+char
        else:
            if char=='[':
                rstr=rstr+char
            break
            
    flipedStr=""
    for x in range(0,len(rstr)):
        x=(len(rstr)-1)-x
        flipedStr=flipedStr+rstr[x]
    
    return flipedStr
    
    
class _DataObject:
    def __init__(self,objType):
        self.data={}
        self.objectType=objType
    objectType=""
    data={}
    def getAllData(self):
        return self.data
    def getAllDataAsStr(self):
        return str(self.data)
    def __getitem__(self,key):
        return self.data[key]
    def __str__(self):
        return self.getAllDataAsStr()
    def getAllObjects(self):
        return self
    def isDataEmpty(self):
        for x in self.data.values():
            if type(x).__name__=="list":
                if len(x)!=0:
                    return False
        return True
    def getObjects(self,objType):
        if objType!="":
            rtb=[]
            for x in self.getAllObjects():
                if x.objectType==objType:
                    rtb.append(x)
            return rtb
        else:
            return self.getAllObjects()
    def equals(self,a):
        return dataEquals(self.data,a.data,3)
class _ParseObject(_DataObject):
    def __init__(self,objType):
        _DataObject.__init__(self,objType)
        self.objectType=objType
        self.isIncluded=False
    def parse(self,p):
        self.data={}
    def getAllObjects(self):
        return self
    def getPathName(self):
        return self.data["namespace"]+"::"+self.data["name"]

def getAllObjectsFromArray(a):
    rtb=[]
    for x in a:
        rtb=rtb+x.getAllObjects()
    return rtb

def isIncludedExt(extent):
    if extent==None or extent.start==None or extent.start.file==None:
        return True
    else:
        return (extent.start.file.name!=parsingFileName)

class _Type(_ParseObject):
    def __init__(self):
        _ParseObject.__init__(self,"Type")
        self.data={"const":None,"templates":None,"fullname":None,"name":None,"isTemplate":None,"isBuiltin":None,"hasTemplate":None,"extra":None,"array":None}
    def parse(self,p):
        self.parseType(p.get_completion_string()[0].spelling,0)
        self.data["array"]=getArrayData(getTextFromSourceRange(p.extent))
        self.data["fullname"]=self.data["fullname"]
        self.isIncluded=isIncludedExt(p.extent)
        
    def setIncludedForAll(self,inc):
        self.isIncluded=inc
        for t in self.getAllTypes(False):
            t.setIncludedForAll(inc)
    def getAllObjects(self):
        return [self]+getAllObjectsFromArray(self.data["templates"])
    def getAllTypes(self,withSelf=True):
        rtb=[]
        if withSelf==True:
            rtb.append(self)
        for t in self.getTemplates():
            rtb=rtb+t.getAllTypes()
        return rtb
    def reloadTemplateName(self):
        self.data["templatename"]=self["name"]
        first=True
        for t in self.data["templates"]:
            if first:
                self.data["templatename"]=self.data["templatename"]+"<"
                first=False
            else:
                self.data["templatename"]=self.data["templatename"]+","
            self.data["templatename"]=self.data["templatename"]+t["fullname"]
        if first==False:
            self.data["templatename"]=self.data["templatename"]+">"
    def parseType(self,fullname,sc=0):
        templates=[]
        templateNum=-1
        allowTemplateNum=0
        name=""
        templateChecking=False
        openedTemplates=0
        sfullname=""
        wasTemplate=0
        nameChecking=True
        self.data["extra"]=""
        for i in range(sc,len(fullname)):
            if fullname[i]=='>':
                openedTemplates=openedTemplates-1
                if openedTemplates==0:
                    wasTemplate=1
                    templateChecking=False
            if templateChecking==True:
                if allowTemplateNum-1 == templateNum and fullname[i]!=' ':
                    templateNum=templateNum+1
                    templates.append(_Type())
                    templates[templateNum].parseType(fullname,i)
                if fullname[i]==',' and openedTemplates==1:
                    allowTemplateNum=allowTemplateNum+1
            if fullname[i]=='<':
                openedTemplates=openedTemplates+1
                self.data["hasTemplate"]=True
                templateChecking=True
            if fullname[i]==',' and openedTemplates==0:
                nameChecking=False
            if openedTemplates>=0 and templateChecking==False and nameChecking==True and fullname[i]!='>':
                if fullname[i]=='*' or fullname[i]=="&":
                    self.data["extra"]=self.data["extra"]+fullname[i]
                else:
                    name=name+fullname[i]
            if openedTemplates>=0 and (wasTemplate==0 or wasTemplate==1) and nameChecking==True:
                if wasTemplate==1:
                    wasTemplate=2
                sfullname=sfullname+fullname[i]
        if name[len(name)-1]==' ':
            name=name[:len(name)-1]
        if name[:5]=="const":
            self.data["const"]=True
            name=name[6:]
        else:
            self.data["const"]=False
        nsts=name.split("::")
        #self.data["namespace"]
        self.data["name"]=nsts[len(nsts)-1]
        self.data["isBuiltin"]=isBuiltinType(name)
        sfullname=sfullname+self.data["extra"]
        self.data["isTemplate"]=hasTemplateLevel(self.data["name"])
        self.data["templates"]=templates
        self.data["fullname"]=sfullname
        self.data["array"]=""
        self.reloadTemplateName()
    def update(self):
        self.reloadFullname()
        self.reloadTemplateName()
    def reloadFullname(self):
        self.data["fullname"]=self.getName()
        if self.data["const"]:
            self.data["fullname"]="const "+self.data["fullname"]
        if self.hasTemplate():
            firstAdd=True
            for i in self.getTemplates():
                if firstAdd==True:
                    self.data["fullname"]=self.data["fullname"]+"<"
                    firstAdd=False
                else:
                    self.data["fullname"]=self.data["fullname"]+","
                i.reloadFullname()
                self.data["fullname"]=self.data["fullname"]+i.getFullname()
            self.data["fullname"]=self.data["fullname"]+">"
        
        
        if self.data["extra"]!="":
            self.data["fullname"]=self.data["fullname"]+" "+self.data["extra"]
        if self.data["array"]!="":
            self.data["fullname"]=self.data["fullname"]+" "+self.data["array"]
    def getName(self):
        return self.data["name"]
    def isTemplate(self):
        return self.data["isTemplate"]
    def getFullname(self):
        return self.data["fullname"]
    def hasTemplate(self):
        return self.data["hasTemplate"]
    def isBuiltin(self):
        return self.data["isBuiltin"]
    def getTemplates(self):
       return self.data["templates"]
    def getExtra(self):
        return self.data["extra"]
    def getArray(self):
        return self.data["array"]
def getTemplates(c):
    ret=[]
    for x in c.get_children():
        if x.kind.name=="TEMPLATE_TYPE_PARAMETER":
            addTemplateLevel(x.get_completion_string()[0].spelling)
            ret.append(x.get_completion_string()[0].spelling)
    return ret

def getParameters(c):
    ret=[]
    for p in c.get_children():
        if p.kind.name=="PARM_DECL":
            v=_Variable("")
            v.parse(p)
            ret.append(v)
    return ret
def isFunction(extent,name,att):
    string=getTextFromSourceRange(extent)
    data=string.split(" ")
    for x in data:
        if x==att:
            return True
        elif x==name:
            return False
    return False


#set of type and name
class _Variable(_ParseObject):
    def __init__(self,ns):
        _ParseObject.__init__(self,"Variable")
        self.data={"namespace":ns,"name":None,"type":None}
    def getAllObjects(self):
        return [self]+self.data["type"].getAllObjects()
    def parse(self,p):
        self.data["type"]=_Type()
        self.data["type"].parse(p)
        self.data["name"]=p.get_completion_string()[1].spelling
        self.isIncluded=isIncludedExt(p.extent)
    def getType(self):
        return self.data["type"]
    def getName(self):
        return self.data["name"]
        
        
        
        
        
class _Function(_ParseObject):
    def __init__(self,ns,method=False):
        _ParseObject.__init__(self,"Function")
        if method:
            self.objectType="Method"
        self.data={"namespace":ns,"static":None,"virtual":None,"name":None,"returnType":None,"parameters":None,"templates":None,"const":None,"isOperator":None,"operator":None}
    def getAllObjects(self):
        return [self]+getAllObjectsFromArray(self["parameters"])+self["returnType"].getAllObjects()
    def parse(self,p):
        increaseTemplateLevel()
        self.data["returnType"]=_Type()
        self.data["returnType"].parse(p)
        self.data["name"]=p.get_completion_string()[1].spelling
        self.data["const"]=False
        self.isIncluded=isIncludedExt(p.extent)
        for cstr in p.get_completion_string():
            if cstr.isKindInformative():
                if cstr.spelling==" const":
                    self.data["const"]=True
        self.data["virtual"]=isFunction(p.extent,self.data["name"],"virtual")
        self.data["static"]=isFunction(p.extent,self.data["name"],"static")
        self.data["templates"]=getTemplates(p)
        self.data["parameters"]=getParameters(p)
        if self.data["name"][:8]=="operator":
            self.data["isOperator"]=True
            self.data["operator"]=self.data["name"][8:]
        else:
            self.data["isOperator"]=False
            self.data["operator"]=""
        decreaseTemplateLevel()
    def getConst(self):
        return self.data["const"]
    def getVirtual(self):
        return self.data["virtual"]
    def getOperator(self):
        return self.data["operator"]
    def isOperator(self):
        return self.data["isOperator"]
    def getName(self):
        return self.data["name"]
    def getReturnType(self):
        return self.data["returnType"]
    def getParameters(self):
        return self.data["parameters"]
    def getTemplates(self):
        return self.data["templates"]
class _ClassConstructor(_ParseObject):
    def __init__(self):
        _ParseObject.__init__(self,"ClassConstructor")
        self.data={"parameters":None}
    
    def getAllObjects(self):
        return [self]+getAllObjectsFromArray(self["parameters"])
    def parse(self,p):
        self.isIncluded=isIncludedExt(p.extent)
        self.data["parameters"]=getParameters(p)
    def getParameters(self):
        return self.data["parameters"]
class _Typedef(_ParseObject):
    def __init__(self,ns):
        _ParseObject.__init__(self,"Typedef")
        self.data={"namespace":ns,"name":None,"type":None}
    def getAllObjects(self):
        if self.data["type"]!=None:
            return [self]+self["type"].getAllObjects()
        else:
            return []
    def parse(self,p):
        if p.spelling=="__builtin_va_list":
            return
        self.isIncluded=isIncludedExt(p.extent)
        self.data["name"]=p.get_completion_string()[0].spelling
        string=getTextFromSourceRange(p.extent)
        if string[:7]=="typedef":
            #Typedef is ok
            string=string[8:]#without typedef keyword
            self.data["type"]=_Type()
            self.data["type"].parseType(string[:len(string)-len(self.data["name"])],0)
        else:
            self.data["type"]=None
            self.data["name"]=None
class _EnumRow(_ParseObject):
    def __init__(self,ns,oldVal):
        _ParseObject.__init__(self,"EnumRow")
        self.data={"namespace":ns,"name":None,"value":oldVal}
    def getAllObjects(self):
        return [self]
    def parse(self,p):
        self.isIncluded=isIncludedExt(p.extent)
        self.data["name"]=p.get_completion_string()[1].spelling
        setValue=None
        for c in p.get_children():
            if c.kind.name=="INTEGER_LITERAL":
                extv=getTextFromSourceRange(c.extent)
                if extv!="":
                    setValue=int(extv,0)
        if setValue==None:
            self.data["value"]=self["value"]+1
        else:
            self.data["value"]=setValue
class _Enum(_ParseObject):
    def __init__(self,ns,inner=False):
        _ParseObject.__init__(self,"Enum")
        self.data={"inner":inner,"namespace":ns,"rows":None,"name":None}
    def getAllObjects(self):
        return [self]+getAllObjectsFromArray(self["rows"])
    def parse(self,p):
        self.isIncluded=isIncludedExt(p.extent)
        self.data["name"]=p.get_completion_string()[0].spelling
        self.data["rows"]=[]
        oldValue=0
        for x in p.get_children():
            if x.kind.name=="ENUM_CONSTANT_DECL":
                c=_EnumRow(self["namespace"]+"::"+self["name"],oldValue)
                c.parse(x)
                oldValue=c["value"]
                self.data["rows"].append(c)


class _ClassData(_DataObject):
    def __init__(self):
        _DataObject.__init__(self,"ClassData")
        self.data={"methods":[],"fields":[],"constructors":[],"classes":[],"typedefs":[],"enums":[]}
    def getAllObjects(self):
        return [self]+getAllObjectsFromArray(self["methods"])+getAllObjectsFromArray(self["fields"])+getAllObjectsFromArray(self["classes"])+getAllObjectsFromArray(self["typedefs"])+getAllObjectsFromArray(self["constructors"])+getAllObjectsFromArray(self["enums"])
    def getMethods(self):
        return self.data["methods"]
    def getConstructors(self):
        return self.data["construtors"]
    def getFields(self):
        return self.data["fields"]
    def getClasses(self):
        return self.data["classes"]
    def merge(self,a):
        if self.isDataEmpty():
            self.data=a.data
        """
        ntbl=[]
        for x in self["classes"]:
            add=True
            for p in ntbl:
                if p["name"]==x["name"]:
                    add=False
                    x.merge(p)
            if add:
                ntbl.append(x)
        self.data["classes"]=ntbl
        self.data["typedefs"]=self["typedefs"]+a["typedefs"]
        self.data["enums"]=self["enums"]+a["enums"]
        """
class _Class(_ParseObject):
    def __init__(self,ns,tp,inner=False):
        _ParseObject.__init__(self,"Class")
        self.data={"namespace":ns,"inner":inner,"name":None,"templates":None,"private":None,"public":None,"protected":None,"type":tp,"base":None}
    def getAllObjects(self):
        return [self]+self["public"].getAllObjects()+self["private"].getAllObjects()+self["protected"].getAllObjects()
    def merge(self,a):
        if a["name"]!=self["name"]:
            return
        if len(self["templates"])!=len(a["templates"]):
            return
        self["public"].merge(a["public"])
        self["private"].merge(a["private"])
        self["protected"].merge(a["protected"])
        if self.isIncluded==False or a.isIncluded==False:
            self.isIncluded=False
        if self["inner"] or a["inner"]:
            self["inner"]=True
    def parse(self,p):
        increaseTemplateLevel()
        self.isIncluded=isIncludedExt(p.extent)
        self.data["name"]=p.get_completion_string()[0].spelling
        self.data["templates"]=getTemplates(p)
        
        self.data["private"]=_ClassData()
        self.data["public"]=_ClassData()
        self.data["protected"]=_ClassData()
        self.data["base"]=[]
        if self.data["type"]=="struct":
            currentData=self.data["public"]
        else:
            currentData=self.data["private"]
        for c in p.get_children():
            if c.kind.name=="ENUM_DECL":
                x=_Enum(self.data["namespace"]+"::"+self.data["name"],True)
                x.parse(c)
                currentData.data["enums"].append(x)
            if c.kind.name=="CXX_BASE_SPECIFIER":
                btype=""
                acc=str(c.get_cxx_access_specifier()).replace("CX_CXX","").lower()
                for x in c.get_children():
                    btype=x.displayname.replace("class ","").replace("union ","").replace("struct ","")
                self.data["base"].append([btype,acc])
            if c.kind.name=="FUNCTION_TEMPLATE" or c.kind.name=="CXX_METHOD":
                x=_Function(self.data["namespace"]+"::"+self.data["name"],True)
                x.parse(c)
                currentData.data["methods"].append(x)
            if c.kind.name=="TYPDEF_DECL":
                x=_Typedef(self.data["namespace"]+"::"+self.data["name"])
                x.parse(c)
                currentData.data["typedefs"].append(x)
            if c.kind.name=="CONSTRUCTOR":
                x=_ClassConstructor()
                x.parse(c)
                currentData.data["constructors"].append(x)
            if c.kind.name=="FIELD_DECL":
                x=_Variable(self.data["namespace"]+"::"+self.data["name"])
                x.parse(c)
                currentData.data["fields"].append(x)
            if c.kind.name=="CXX_ACCESS_SPEC_DECL":
                currentData=self.data[c.get_cxx_access_specifier().name.replace("CX_CXX","").lower()]
            if c.kind.name=="CLASS_DECL" or c.kind.name=="CLASS_TEMPLATE" or c.kind.name=="STRUCT_DECL" or c.kind.name=="UNION_DECL":
                nm="class"
                if c.kind.name=="UNION_DECL":
                    nm="union"
                if c.kind.name=="STRUCT_DECL":
                    nm="struct"
                x=_Class(self.data["namespace"]+"::"+self.data["name"],nm,True)
                x.parse(c)
                currentData.data["classes"].append(x)
        
        decreaseTemplateLevel()
                
    def getPrivate(self):
        return self.data["private"]
    def getPublic(self):
        return self.data["public"]
    def getProtected(self):
        return self.data["protected"]
    def getName(self):
        return self.data["name"]
    def getTemplate(self):
        return self.data["templates"]



class _Namespace(_ParseObject):
    def __init__(self,ns=""):
        _ParseObject.__init__(self,"Namespace")
        self.data={"namespace":ns,"name":None,"namespaces":None,"classes":None,"functions":None,"variables":None,"typedefs":None,"enums":None,"isGlobal":None} 
    def getAllObjects(self):
        return [self]+getAllObjectsFromArray(self["namespaces"])+getAllObjectsFromArray(self["classes"])+getAllObjectsFromArray(self["functions"])+getAllObjectsFromArray(self["typedefs"])+getAllObjectsFromArray(self["variables"])+getAllObjectsFromArray(self["enums"])
    def mergeTable(self,a,nm):
        newTb=[]
        for x in self.data[nm]:
            newTb.append(x)
        for x in a.data[nm]:
            add=True
            for p in newTb:
                if x.equals(p)==True:
                    if p.isIncluded==False or x.isIncluded==False:
                        p.isIncluded=False
                    add=False
            if add==True:
                newTb.append(x)
        self.data[nm]=newTb
    def mergeNamespace(self,a,onlyNoincluded=True):
        newTb=[]
        for x in self.data["namespaces"]:
            if onlyNoincluded==True:
                if x.isIncluded==True:
                    continue
            add=True
            for p in newTb:
                if p.data["name"]==x.data["name"] and p.data["namespace"]==x.data["namespace"]:
                    p.merge(x,onlyNoincluded)
                    add=False
            if add==True:
                newTb.append(x)
        
        for x in a.data["namespaces"]:
            if onlyNoincluded==True:
                if x.isIncluded==True:
                    continue
            add=True
            for p in newTb:
                if p.data["name"]==x.data["name"] and p.data["namespace"]==x.data["namespace"]:
                    p.merge(x,onlyNoincluded)
                    add=False
            if add==True:
                newTb.append(x)
        self.data["namespaces"]=newTb
    def merge(self,a,onlyNoincluded=True):
        newTb=[]
        for x in self.data["classes"]:
            newTb.append(x)
        for x in a.data["classes"]:
            add=True
            for p in newTb:
                if x["name"]==p["name"]:
                    add=False
                    x.merge(p)
            if add==True:
                newTb.append(x)
        if a.isIncluded==False or self.isIncluded:
            self.isIncluded=False
        self.data["classes"]=newTb
        self.mergeTable(a,"functions")
        self.mergeTable(a,"variables")
        self.mergeTable(a,"typedefs")
        self.mergeTable(a,"enums")
        self.mergeNamespace(a,onlyNoincluded)
    def parse(self,p,parseIncluded=True):
        addNs=""
        
        self.isIncluded=isIncludedExt(p.extent)
        
        if p.kind.name!="NAMESPACE":
            self.data["name"]=""
            self.data["isGlobal"]=True 
        else:
            self.data["name"]=p.get_completion_string()[0].spelling
            self.data["isGlobal"]=False
            
            if self.data["namespace"]!="":
                addNs="::"+self.data["name"]
            else:
                addNs=self.data["name"]
        self.data["namespaces"]=[]
        self.data["classes"]=[]
        self.data["functions"]=[]
        self.data["variables"]=[]
        self.data["typedefs"]=[]
        self.data["enums"]=[]
        for x in p.get_children():
            if (x.kind.name=="CLASS_DECL" or x.kind.name=="CLASS_TEMPLATE" or x.kind.name=="STRUCT_DECL" or x.kind.name=="UNION_DECL") and (parseIncluded==False or isIncludedExt(x.extent)==False):
                if (x.get_completion_string()[0].spelling=="type_info" and self.data["isGlobal"]==True)==False:
                    nm="class"
                    if x.kind.name=="UNION_DECL":
                        nm="union"
                    if x.kind.name=="STRUCT_DECL":
                        nm="struct"
                    v=_Class(self.data["namespace"]+addNs,nm)
                    v.parse(x)
                    self.data["classes"].append(v)
            if x.kind.name=="NAMESPACE" and (parseIncluded==False or isIncludedExt(x.extent)==False):
                v=_Namespace(self.data["namespace"]+addNs)
                v.parse(x,parseIncluded)
                self.data["namespaces"].append(v)
            if x.kind.name=="FUNCTION_DECL" or x.kind.name=="FUNCTION_TEMPLATE" and (parseIncluded==False or isIncludedExt(x.extent)==False):
                v=_Function(self.data["namespace"]+addNs)
                v.parse(x)
                self.data["functions"].append(v)
            if x.kind.name=="TYPEDEF_DECL" and (parseIncluded==False or isIncludedExt(x.extent)==False):
                v=_Typedef(self.data["namespace"]+addNs)
                v.parse(x)
                self.data["typedefs"].append(v)
            if x.kind.name=="VAR_DECL" and (parseIncluded==False or isIncludedExt(x.extent)==False):
                v=_Variable(self.data["namespace"]+addNs)
                v.parse(x)
                self.data["variables"].append(v)
            if x.kind.name=="ENUM_DECL" and (parseIncluded==False or isIncludedExt(x.extent)==False):
                v=_Enum(self.data["namespace"]+addNs)
                v.parse(x)
                self.data["enums"].append(v)
                
def parse(fi,autoMerge=-1,parseIncluded=True):
    indx=clang.cindex.Index.create()
    loadFileData(fi)
    tu=indx.parse(fi)
    global parsingFileName
    parsingFileName=tu.cursor.extent.start.file.name
    gNs=_Namespace()
    gNs.parse(tu.cursor,parseIncluded)
    if autoMerge==1 or autoMerge==0:
        gNs.mergeNamespace(gNs,autoMerge==1)
    return gNs
